package com.link2room.aeriabots.facade.impl;

import com.link2room.aeriabots.constant.WXConstant;
import com.link2room.aeriabots.dto.result.base.WxPayOptionDto;
import com.link2room.aeriabots.service.IWxComponentService;
import com.link2room.common.constant.BaseConstant;
import com.link2room.common.constant.DefaultValue;
import com.link2room.common.enums.BaseSysExceptionEnum;
import com.link2room.common.exception.SysException;
import com.link2room.common.service.ICommonService;
import com.link2room.common.util.ClassConverUtil;
import com.link2room.common.util.StringUtil;
import com.link2room.aeriabots.entity.WxCertificate;
import com.link2room.aeriabots.entity.WxComponent;
import com.link2room.aeriabots.entity.WxPayOption;
import com.link2room.enums.exception.AeriabotsSysExceptionEnum;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import com.tencent.client.OfficialAccountClient;
import com.tencent.client.WXPayClient;
import com.tencent.protocol.component.get_jspticket_protocol.JspTicketResDate;

import javax.annotation.Resource;

/**
 * Created by LN on 2016/9/18.
 */
public class BaseFacade {

    @Resource
    private IWxComponentService wxComponentService;
    @Resource
    protected ICommonService commonService;
    protected String getComponentAppid() throws Exception {
        WxComponent cAppid = wxComponentService.findByItem(DefaultValue.LHOTEL_GROUP_CODE, DefaultValue.LHOTEL_CODE, WXConstant.WxCertificate.COMPONENT_APPID);
        if(cAppid != null){
            return cAppid.getValue();
        } else {
            throw new SysException(AeriabotsSysExceptionEnum.NO_COMPONENT_APPID);
        }
    }
    protected String getComponentAccessToken() throws Exception {
        WxComponent cat = wxComponentService.findByItem(DefaultValue.LHOTEL_GROUP_CODE, DefaultValue.LHOTEL_CODE, WXConstant.WxCertificate.COMPONENT_ACCESS_TOKEN);
        if(cat == null){
            throw new SysException(AeriabotsSysExceptionEnum.NO_COMPONENT_ACCESS_TOKEN);
        }
        return cat.getValue();
    }

    protected String getComponentToken() throws Exception {
        WxComponent cat = wxComponentService.findByItem(DefaultValue.LHOTEL_GROUP_CODE, DefaultValue.LHOTEL_CODE, WXConstant.WxCertificate.COMPONENT_TOKEN);
        if(cat == null){
            throw new SysException(AeriabotsSysExceptionEnum.NO_COMPONENT_ACCESS_TOKEN);
        }
        return cat.getValue();
    }

    protected WxCertificate getWxCertificate(String lhotelGorupCode, String lhotelCode) throws Exception {
        if(StringUtil.isEmpty(lhotelGorupCode)){
            throw new SysException(BaseSysExceptionEnum.INVALID_PARA.getCode(), BaseSysExceptionEnum.INVALID_PARA.getMsg()+"[lhotelGorupCode] is null", BaseConstant.SysExceptionConstant.BIZ_TYPE.AERIABOTS);
        }
        if(StringUtil.isEmpty(lhotelCode)){
            lhotelCode = DefaultValue.LHOTEL_CODE;
        }
        WxCertificate wc = commonService.findOneEQ(WxCertificate.class, new WxCertificate(lhotelGorupCode, lhotelCode));
        if(wc == null || StringUtil.isBlank(wc.getAppid())){
            throw new SysException(AeriabotsSysExceptionEnum.NO_APPID);
        }
        return wc;
    }
    protected WxCertificate getWxCertificateByAliasName(String appAliasName) throws Exception {
        WxCertificate find = new WxCertificate();
        find.setAppAliasName(appAliasName);
        WxCertificate wc = commonService.findOneEQ(WxCertificate.class, find);
        if(wc == null || StringUtil.isBlank(wc.getAppid())){
            throw new SysException(AeriabotsSysExceptionEnum.NO_APPID);
        }
        return wc;
    }

    protected WxCertificate getWxCertificateByAppid(String appid) throws Exception {
        WxCertificate wc = commonService.findOneEQ(WxCertificate.class, new WxCertificate(appid));
        if(wc == null || StringUtil.isBlank(wc.getAppid())){
            throw new SysException(AeriabotsSysExceptionEnum.NO_APPID);
        }
        return wc;
    }

    protected String getComponentEncodingAesKey() throws Exception {
        WxComponent cat = wxComponentService.findByItem(DefaultValue.LHOTEL_GROUP_CODE, DefaultValue.LHOTEL_CODE, WXConstant.WxCertificate.COMPONENT_ENCODINGAESKEY);
        if(cat == null){
            throw new SysException(AeriabotsSysExceptionEnum.NO_ENCODING_AES_KEY);
        }
        return cat.getValue();
    }
    protected String getPayNotifyUrl() throws Exception{
        WxComponent cat = wxComponentService.findByItem(DefaultValue.LHOTEL_GROUP_CODE, DefaultValue.LHOTEL_CODE, WXConstant.WxCertificate.WX_PAY_NOTIFY_URL);
        if(cat == null){
            throw new SysException(AeriabotsSysExceptionEnum.NO_ENCODING_AES_KEY);
        }
        return cat.getValue();
    }

    /**
     * 微信postData解码
     * @param msgSignature
     * @param timeStamp
     * @param nonce
     * @param postData
     * @return
     * @throws Exception
     */
    protected String wxBizMsgCryptDecryptMsg(String msgSignature, String timeStamp, String nonce, String postData) throws Exception{
        String componentAppid = this.getComponentAppid();
        String componentToken = this.getComponentToken();
        String encodingAesKey = this.getComponentEncodingAesKey();
        return (new WXBizMsgCrypt(componentToken , encodingAesKey, componentAppid)).decryptMsg(msgSignature, timeStamp, nonce, postData);
    }

    protected WXBizMsgCrypt.EncryptBody wxBizMsgCryptEncryptBody(String replyMsg, String timeStamp, String nonce) throws Exception {
        String componentAppid = this.getComponentAppid();
        String componentToken = this.getComponentToken();
        String encodingAesKey = this.getComponentEncodingAesKey();
        return (new WXBizMsgCrypt(componentToken , encodingAesKey, componentAppid)).encryptBody(replyMsg, timeStamp, nonce);
    }


    /**
     * 请求获取jspTicket用于微信公众号支付
     * @param officeAccountAccessToke
     * @return
     * @throws Exception
     */
    protected String requsetWxJspTicket(String officeAccountAccessToke) throws Exception {
        JspTicketResDate res = OfficialAccountClient.requestJspTicketResDate(officeAccountAccessToke);
        if(StringUtil.isNotBlank(res.getTicket())){
            return res.getTicket();
        }else{
            throw new SysException(AeriabotsSysExceptionEnum.WX_SDK_ERROR.getCode(), AeriabotsSysExceptionEnum.WX_SDK_ERROR.getMsg()+" "+res.getErrcode()+","+res.getErrmsg(), AeriabotsSysExceptionEnum.WX_SDK_ERROR.getBizType());
        }
    }

    /**
     * 获取微信注册链接
     * @return
     */
    protected String getWxRegisterUrl(String lhotelGroupCode) throws Exception {
        WxComponent cat = wxComponentService.findByItem(lhotelGroupCode, DefaultValue.LHOTEL_CODE, WXConstant.WxCertificate.WX_REGISTER_URL);
        if(cat == null){
            throw new SysException(AeriabotsSysExceptionEnum.WX_REGISTER_URL);
        }
        return cat.getValue();
    }

    /**
     * 获取会员升级页面
     * @param lhotelGroupCode
     * @return
     * @throws Exception
     */
    protected String getLevelUpRrl(String lhotelGroupCode) throws Exception {

        WxComponent cat = wxComponentService.findByItem(lhotelGroupCode, DefaultValue.LHOTEL_CODE, WXConstant.WxCertificate.MEMBER_LEVEL_UP_URL);
        if(cat == null){
            throw new SysException(AeriabotsSysExceptionEnum.WX_REGISTER_URL,WXConstant.WxCertificate.MEMBER_LEVEL_UP_URL+"注册页面不存在");
        }
        return cat.getValue();

    }
    protected WXPayClient getWxClient(String lhotelGroupCode) throws Exception {
        WxPayOptionDto payOpt = getWxPayOptionDto(lhotelGroupCode);
        String key = "";
        String appid = "";
        String mchID = "";
        String subAppid = "";
        String subMchID = "";
        String certLocalPath = "";
        String certPassword = "";
        WXPayClient client;
        if(payOpt.isSubMch()){
            WxPayOptionDto parentOpt = payOpt.getParentPayOption();
            key = parentOpt.getWxPayKey();
            appid = parentOpt.getAppid();
            mchID=parentOpt.getWxMchId();
            subAppid=payOpt.getAppid();
            subMchID= payOpt.getWxMchId();
            certLocalPath = parentOpt.getCertLocalPath();
            certPassword = parentOpt.getCertPassword();
            if(StringUtil.isBlank(certPassword)){
                certPassword = mchID;
            }
            client = new WXPayClient(payOpt.isSubMch(),key,appid,mchID,subAppid,subMchID,certLocalPath,certPassword);
        }else{
            key = payOpt.getWxPayKey();
            appid = payOpt.getAppid();
            mchID=payOpt.getWxMchId();
            certLocalPath = payOpt.getCertLocalPath();
            certPassword = payOpt.getCertPassword();
            if(StringUtil.isBlank(certPassword)){
                certPassword = mchID;
            }
            client = new WXPayClient(key,appid,mchID,subMchID,certLocalPath,certPassword);
        }
        return client;
    }

    protected WxPayOptionDto getWxPayOptionDto(String lhotelGroupCode) throws Exception {
        WxPayOptionDto wxPayOptionDto = new WxPayOptionDto();
        WxPayOptionDto parentOptionDto = new WxPayOptionDto();
        if(StringUtil.isBlank(lhotelGroupCode)){
            throw new SysException(BaseSysExceptionEnum.INVALID_PARA.getCode(), BaseSysExceptionEnum.INVALID_PARA.getMsg()+"lhotelGroupCode is null", BaseSysExceptionEnum.INVALID_PARA.getBizType());
        }
        WxPayOption find = new WxPayOption();
        find.setLhotelGroupCode(lhotelGroupCode);
        find.setIsHalt("F");
        find.setIsSubMch("T");
        WxPayOption payOPT = commonService.findOneEQ(WxPayOption.class, find);
        WxPayOption parentOPT = null;
        if(payOPT == null){
            throw new SysException(AeriabotsSysExceptionEnum.NO_WX_PAY_OPT.getCode(), AeriabotsSysExceptionEnum.NO_WX_PAY_OPT.getMsg()+"lhotelGroupCode:"+lhotelGroupCode, AeriabotsSysExceptionEnum.NO_WX_PAY_OPT.getBizType());
        }
        ClassConverUtil.copyProperties(payOPT,wxPayOptionDto);

        //查找parenOption
        if("T".equals(payOPT.getIsSubMch())){
            String parenAppid = payOPT.getParentAppid();
            if(StringUtil.isNotBlank(parenAppid)){
                WxPayOption findParent = new WxPayOption();
                findParent.setAppid(parenAppid);
                findParent.setIsHalt("F");
                findParent.setIsSubMch("F");
                parentOPT = commonService.findOneEQ(WxPayOption.class, findParent);
                if(parentOPT!=null){
                    ClassConverUtil.copyProperties(parentOPT,parentOptionDto);
                }
                wxPayOptionDto.setParentPayOption(parentOptionDto);
                wxPayOptionDto.setSubMch(true);
            }
        }
        return wxPayOptionDto;
    }


    /**
     * HTTPS加密支付client
     * @param lhotelGroupCode
     * @return
     * @throws Exception
     */
    protected WXPayClient getPromotionTransfersControllerCertWxClient(String lhotelGroupCode) throws Exception {
        WxPayOptionDto option= getWxPayOptionDto(lhotelGroupCode);
        String mchid =  option.getCorpidMchID();
        String appid = option.getAppid();
        String key = option.getWxPayKey();
        String sdbMchID = "";
        String certLocalPath = option.getCertLocalPath();
        String certPassword = option.getCertPassword();
        if(StringUtil.isBlank(certPassword)){
            certPassword = mchid;
        }
        WXPayClient client = new WXPayClient(key,appid,mchid,sdbMchID,certLocalPath,certPassword);
        return client;
    }
    /**
     * 生成规则: 单号+DefaultValue.MARK+lhotelGroupCode
     * @param l2rNo
     * @return
     */
    protected String createPayNo(String l2rNo,String lhotelGroupCode){
        return l2rNo+ DefaultValue.MARK+lhotelGroupCode;
    }

}
